#define GTK_CSS_CHANGE_GOT_MATCH GTK_CSS_CHANGE_RESERVED_BIT
typedef struct _GtkCssSelectorClass GtkCssSelectorClass;
+typedef gboolean (* GtkCssSelectorForeachFunc) (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ gpointer data);
struct _GtkCssSelectorClass {
const char *name;
void (* print) (const GtkCssSelector *selector,
GString *string);
+ /* NULL or an iterator that calls func with each submatcher of @matcher.
+ * Potentially no submatcher exissts.
+ * If any @invocation of @func returns %TRUE, the function will immediately
+ * return %TRUE itself. If @func never returns %TRUE (or isn't called at all),
+ * %FALSE will be returned.
+ */
+ gboolean (* foreach_matcher) (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data);
gboolean (* match_one) (const GtkCssSelector *selector,
const GtkCssMatcher *matcher);
- gboolean (* match) (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher);
void (* tree_match) (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher,
GHashTable *res);
gtk_css_selector_match (const GtkCssSelector *selector,
const GtkCssMatcher *matcher)
{
- if (selector == NULL)
- return TRUE;
+ return selector->class->match_one (selector, matcher);
+}
- return selector->class->match (selector, matcher);
+static gboolean
+gtk_css_selector_foreach (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
+{
+ return selector->class->foreach_matcher (selector, matcher, func, data);
}
static int
}
static gboolean
-gtk_css_selector_default_match_one (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_default_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
- return TRUE;
+ return func (selector, matcher, data);
}
static gboolean
-gtk_css_selector_default_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_default_match_one (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher)
{
- if (!selector->class->match_one (selector, matcher))
- return FALSE;
-
- return gtk_css_selector_match (gtk_css_selector_previous (selector), matcher);
+ return TRUE;
}
static void
}
static gboolean
-gtk_css_selector_descendant_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_descendant_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
GtkCssMatcher ancestor;
{
matcher = &ancestor;
- if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
+ if (func (selector, &ancestor, data))
return TRUE;
+
+ /* any matchers are dangerous here, as we may loop forever, but
+ we can terminate now as all possible matches have already been added */
+ if (_gtk_css_matcher_matches_any (matcher))
+ break;
}
return FALSE;
static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT = {
"descendant",
gtk_css_selector_descendant_print,
+ gtk_css_selector_descendant_foreach_matcher,
gtk_css_selector_default_match_one,
- gtk_css_selector_descendant_match,
gtk_css_selector_descendant_tree_match,
gtk_css_selector_descendant_get_change,
gtk_css_selector_descendant_tree_get_change,
}
static gboolean
-gtk_css_selector_descendant_for_region_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_descendant_for_region_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
GtkCssMatcher ancestor;
if (_gtk_css_matcher_has_regions (matcher))
{
- if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
+ if (func (selector, matcher, data))
return TRUE;
}
{
matcher = &ancestor;
- if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
+ if (func (selector, matcher, data))
return TRUE;
+
+ /* any matchers are dangerous here, as we may loop forever, but
+ we can terminate now as all possible matches have already been added */
+ if (_gtk_css_matcher_matches_any (matcher))
+ break;
}
return FALSE;
static const GtkCssSelectorClass GTK_CSS_SELECTOR_DESCENDANT_FOR_REGION = {
"descendant_for_region",
gtk_css_selector_descendant_for_region_print,
+ gtk_css_selector_descendant_for_region_foreach_matcher,
gtk_css_selector_default_match_one,
- gtk_css_selector_descendant_for_region_match,
gtk_css_selector_descendant_for_region_tree_match,
gtk_css_selector_descendant_for_region_get_change,
gtk_css_selector_descendant_for_region_tree_get_change,
}
static gboolean
-gtk_css_selector_child_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_child_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
GtkCssMatcher parent;
if (!_gtk_css_matcher_get_parent (&parent, matcher))
return FALSE;
- return gtk_css_selector_match (gtk_css_selector_previous (selector), &parent);
+ return func (selector, &parent, data);
}
static void
static const GtkCssSelectorClass GTK_CSS_SELECTOR_CHILD = {
"child",
gtk_css_selector_child_print,
+ gtk_css_selector_child_foreach_matcher,
gtk_css_selector_default_match_one,
- gtk_css_selector_child_match,
gtk_css_selector_child_tree_match,
gtk_css_selector_child_get_change,
gtk_css_selector_child_tree_get_change,
}
static gboolean
-gtk_css_selector_sibling_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_sibling_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
GtkCssMatcher previous;
{
matcher = &previous;
- if (gtk_css_selector_match (gtk_css_selector_previous (selector), matcher))
+ if (func (selector, matcher, data))
return TRUE;
+
+ /* any matchers are dangerous here, as we may loop forever, but
+ we can terminate now as all possible matches have already been added */
+ if (_gtk_css_matcher_matches_any (matcher))
+ break;
}
return FALSE;
static const GtkCssSelectorClass GTK_CSS_SELECTOR_SIBLING = {
"sibling",
gtk_css_selector_sibling_print,
+ gtk_css_selector_sibling_foreach_matcher,
gtk_css_selector_default_match_one,
- gtk_css_selector_sibling_match,
gtk_css_selector_sibling_tree_match,
gtk_css_selector_sibling_get_change,
gtk_css_selector_sibling_tree_get_change,
}
static gboolean
-gtk_css_selector_adjacent_match (const GtkCssSelector *selector,
- const GtkCssMatcher *matcher)
+gtk_css_selector_adjacent_foreach_matcher (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ GtkCssSelectorForeachFunc func,
+ gpointer data)
{
GtkCssMatcher previous;
if (!_gtk_css_matcher_get_previous (&previous, matcher))
return FALSE;
-
- return gtk_css_selector_match (gtk_css_selector_previous (selector), &previous);
+
+ return func (selector, &previous, data);
}
static void
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ADJACENT = {
"adjacent",
gtk_css_selector_adjacent_print,
+ gtk_css_selector_adjacent_foreach_matcher,
gtk_css_selector_default_match_one,
- gtk_css_selector_adjacent_match,
gtk_css_selector_adjacent_tree_match,
gtk_css_selector_adjacent_get_change,
gtk_css_selector_adjacent_tree_get_change,
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
G_STRINGIFY(n), \
gtk_css_selector_ ## n ## _print, \
+ gtk_css_selector_default_foreach_matcher, \
match_func, \
- gtk_css_selector_default_match, \
gtk_css_selector_default_tree_match, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
static const GtkCssSelectorClass GTK_CSS_SELECTOR_NOT_ ## c = { \
"not_" G_STRINGIFY(n), \
gtk_css_selector_not_ ## n ## _print, \
+ gtk_css_selector_default_foreach_matcher, \
gtk_css_selector_not_ ## n ## _match_one, \
- gtk_css_selector_default_match, \
gtk_css_selector_default_tree_match, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
static const GtkCssSelectorClass GTK_CSS_SELECTOR_REGION = {
"region",
gtk_css_selector_region_print,
+ gtk_css_selector_default_foreach_matcher,
gtk_css_selector_region_match_one,
- gtk_css_selector_default_match,
gtk_css_selector_default_tree_match,
gtk_css_selector_region_get_change,
gtk_css_selector_region_tree_get_change,
return change;
}
+static gboolean
+gtk_css_selector_foreach_match (const GtkCssSelector *selector,
+ const GtkCssMatcher *matcher,
+ gpointer unused)
+{
+ selector = gtk_css_selector_previous (selector);
+
+ if (selector == NULL)
+ return TRUE;
+
+ if (!gtk_css_selector_match (selector, matcher))
+ return FALSE;
+
+ return gtk_css_selector_foreach (selector, matcher, gtk_css_selector_foreach_match, NULL);
+}
+
/**
* _gtk_css_selector_matches:
* @selector: the selector
update_type_references ();
- return gtk_css_selector_match (selector, matcher);
+ if (!gtk_css_selector_match (selector, matcher))
+ return FALSE;
+
+ return gtk_css_selector_foreach (selector, matcher, gtk_css_selector_foreach_match, NULL);
}
/* Computes specificity according to CSS 2.1.